package com.gcb.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcb.common.constant.CommonConstants;
import com.gcb.common.core.domain.entity.GcbUser;
import com.gcb.common.enums.AuthStatusEnum;
import com.gcb.common.enums.CommonStatusEnum;
import com.gcb.common.enums.CreateTypeEnum;
import com.gcb.common.enums.GcbUserTypeEnum;
import com.gcb.common.exception.ServiceException;
import com.gcb.dao.CompanyUserDao;
import com.gcb.domain.dto.CompanyUserAuditSaveDTO;
import com.gcb.domain.dto.CompanyUserQueryDTO;
import com.gcb.domain.dto.CompanyUserSaveDTO;
import com.gcb.domain.entity.Company;
import com.gcb.domain.entity.CompanyUser;
import com.gcb.domain.entity.CompanyUserAudit;
import com.gcb.domain.vo.CompanyUserVO;
import com.gcb.mapper.CompanyUserMapper;
import com.gcb.service.ICompanyService;
import com.gcb.service.ICompanyUserAuditService;
import com.gcb.service.ICompanyUserService;
import com.gcb.service.IGcbUserService;
import com.gcb.utils.GcbUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.gcb.common.constant.CommonConstants.CompanyUser.*;
import static com.gcb.common.enums.GcbUserTypeEnum.COMPANY_SUPER_ADMIN;

/**
 * 工船宝企业用户关系Service业务层处理
 *
 * @author seh
 * @date 2024-03-08
 */
@Service
public class CompanyUserServiceImpl extends ServiceImpl<CompanyUserMapper, CompanyUser> implements ICompanyUserService {
    @Resource
    private CompanyUserMapper companyUserMapper;

    @Resource
    @Lazy
    private ICompanyService companyService;

    @Resource
    private IGcbUserService gcbUserService;

    @Resource
    private ICompanyUserAuditService companyUserAuditService;

    @Resource
    private CompanyUserDao companyUserDao;

    @Autowired
    private GcbUtils gcbUtils;

    @Override
    public List<CompanyUserVO> selectCompanyUserByUserId(Long userId) {
        List<CompanyUserVO> list = companyUserMapper.selectCompanyUserByUserId(userId);
        list.forEach(item -> {
            item.setUserTypeStr(GcbUserTypeEnum.getInfo(item.getUserType()));
            item.setCompanyAuthStatusStr(AuthStatusEnum.getInfo(item.getCompanyAuthStatus()));
            item.setWaterStatusStr(AuthStatusEnum.getInfo(item.getWaterStatus()));
            item.setCompanyStatusStr(CommonStatusEnum.getInfo(item.getCompanyStatus()));
        });
        return list;
    }

    @Override
    public List<CompanyUserVO> getMembersByCompanyId(Long companyId) {
        List<CompanyUserVO> list = companyUserMapper.selectCompanyUserByCompanyId(companyId);
        return list.stream().peek(item -> {
            item.setUserAuthStatusStr(AuthStatusEnum.getInfo(item.getUserAuthStatus()));
            item.setCrewAuthStatusStr(AuthStatusEnum.getInfo(item.getCrewAuthStatus()));
            item.setUserTypeStr(GcbUserTypeEnum.getInfo(item.getUserType()));
            item.setUserStatusStr(CommonStatusEnum.getInfo(item.getUserStatus()));
            Integer crewAuthStatus = item.getCrewAuthStatus();
            if(Validator.isNull(crewAuthStatus)) {
                item.setCrewAuthStatus(0);
                item.setCrewAuthStatusStr("未认证");
            }
        }).collect(Collectors.toList());
    }

    @Override
    public List<CompanyUserVO> getMembersByCompanyIdWithoutUserId(Long companyId, Long userId) {
        List<CompanyUserVO> list = companyUserMapper.selectMembersByCompanyIdWithoutUserId(companyId, userId);
        return list.stream().peek(item -> {
            item.setUserAuthStatusStr(AuthStatusEnum.getInfo(item.getUserAuthStatus()));
            item.setCrewAuthStatusStr(AuthStatusEnum.getInfo(item.getCrewAuthStatus()));
            item.setUserTypeStr(GcbUserTypeEnum.getInfo(item.getUserType()));
            item.setUserStatusStr(CommonStatusEnum.getInfo(item.getUserStatus()));
        }).collect(Collectors.toList());
    }

    @Override
    public CompanyUser getLeaderByCompanyId(Long companyId) {
        LambdaQueryWrapper<CompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CompanyUser::getType, COMPANY_SUPER_ADMIN.getCode());
        wrapper.eq(CompanyUser::getCompanyId, companyId);
        return companyUserDao.getOne(wrapper);
    }

    /**
     * 查询工船宝企业用户关系列表
     *
     * @param dto 查询条件
     * @return 工船宝企业用户关系
     */
    @Override
    public List<CompanyUserVO> list(CompanyUserQueryDTO dto) {
        List<CompanyUserVO> list = companyUserMapper.list(dto);
        list.forEach(item -> {
            item.setCompanyAuthStatusStr(AuthStatusEnum.getInfo(item.getCompanyAuthStatus()));
            item.setUserTypeStr(GcbUserTypeEnum.getInfo(item.getUserType()));
        });
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void joinCompany(CompanyUserAuditSaveDTO dto) {
        //都不为空说明是h5进来注册并创建然后加入企业
        if (StrUtil.isNotBlank(dto.getPhone()) && StrUtil.isNotBlank(dto.getName())) {
            GcbUser existUser = gcbUserService.getOne(new LambdaQueryWrapper<GcbUser>()
                    .eq(GcbUser::getMobile, dto.getPhone()));
            if (ObjUtil.isNull(existUser)) {
                GcbUser gcbUser = gcbUtils.initUserInfo(dto.getPhone(), CreateTypeEnum.USER, 0L);
                if (!gcbUserService.save(gcbUser)) throw new ServiceException("创建用户失败");
                //如果是H5进来跳过token jwt无法取得id
                dto.setUserId(gcbUser.getId());
            } else {
                //说明H5页面进来但是已经有账号了 不需要注册
                dto.setUserId(existUser.getId());
            }
        }

        //查询企业信息 如果为空说明企业编码不对 抛业务异常
        Company company = companyService.getOne(new LambdaQueryWrapper<Company>()
                .eq(Company::getCompanyCode, dto.getCompanyCode())
                .eq(Company::getStatus, CommonConstants.Company.STATUS_NORMAL));
        if (ObjUtil.isNull(company)) {
            if (TYPE_BY_QRCODE.equals(dto.getType())) {
                throw new ServiceException("当前二维码无法识别,请核查二维码无误后再进行扫码");
            }
            if (TYPE_BY_COMPANY_CODE.equals(dto.getType())) {
                throw new ServiceException("当前企业码无效,请核查修改后再进行加入");
            }
            if (TYPE_BY_H5.equals(dto.getType())) {
                throw new ServiceException("当前企业码无效,请核查修改后再进行加入");
            } else {
                throw new ServiceException("当前企业码无效,请核查修改后再进行加入");
            }
        }

        //如果关联表已经存在在职状态 说明已经是企业成员
        CompanyUser companyUser = this.getOne(new LambdaQueryWrapper<CompanyUser>()
                .eq(CompanyUser::getCompanyId, company.getId())
                .eq(CompanyUser::getUserId, dto.getUserId())
                .eq(CompanyUser::getStatus, STATE_NORMAL));
        if (ObjUtil.isNotNull(companyUser)) {
            throw new ServiceException("您已是该企业成员,无需申请加入");
        }

        //只查询审核中或者未审核的 有且只有一条
        CompanyUserAudit existAudit = companyUserAuditService.getOne(new LambdaQueryWrapper<CompanyUserAudit>()
                .eq(CompanyUserAudit::getCompanyId, company.getId())
                .eq(CompanyUserAudit::getUserId, dto.getUserId())
                .and(x -> x.eq(CompanyUserAudit::getAuthStatus, AuthStatusEnum.AUDITING.getCode()).or()
                        .eq(CompanyUserAudit::getAuthStatus, AuthStatusEnum.UN_VERIFIED.getCode())));
        if (ObjUtil.isNotNull(existAudit)) {
            throw new ServiceException("您已申请加入企业,无需重复提交");
        }

        CompanyUserAudit userAudit = new CompanyUserAudit();
        userAudit.setCompanyId(company.getId());
        userAudit.setUserId(dto.getUserId());
        userAudit.setAuthStatus(AuthStatusEnum.AUDITING.getCode());
        userAudit.setInviteBy(dto.getInviteId());
        userAudit.setSource(dto.getSource());
        companyUserAuditService.save(userAudit);
        userAudit.setCreateBy(dto.getUserId());
    }


    @Override
    public void editType(CompanyUserSaveDTO dto) {
        CompanyUser companyUser = this.getOne(new LambdaQueryWrapper<CompanyUser>()
                .eq(CompanyUser::getUserId, dto.getUserId())
                .eq(CompanyUser::getStatus, STATE_NORMAL)
                .eq(CompanyUser::getCompanyId, dto.getCompanyId()));
        if (GcbUserTypeEnum.COMPANY_SUPER_ADMIN.getCode().equals(companyUser.getType())) {
            throw new ServiceException("企业超级管理员不能修改角色类型");
        }

        boolean update = this.update(new LambdaUpdateWrapper<CompanyUser>()
                .eq(CompanyUser::getCompanyId, dto.getCompanyId())
                .eq(CompanyUser::getUserId, dto.getUserId())
                .eq(CompanyUser::getStatus, STATE_NORMAL)
                .set(CompanyUser::getType, dto.getType()));
        if (!update) {
            throw new ServiceException("切换角色类型失败");
        }
    }

    @Override
    public void editStatus(CompanyUserSaveDTO dto) {
        CompanyUser companyUser = this.getOne(new LambdaQueryWrapper<CompanyUser>()
                .eq(CompanyUser::getUserId, dto.getUserId())
                .eq(CompanyUser::getStatus, STATE_NORMAL)
                .eq(CompanyUser::getCompanyId, dto.getCompanyId()));
        if (ObjUtil.isNull(companyUser)) {
            throw new ServiceException("该用户不存在或已离职");
        }
        if (COMPANY_SUPER_ADMIN.getCode().equals(companyUser.getType())) {
            throw new ServiceException("不能移除企业超级管理员");
        }

        boolean update = this.update(new LambdaUpdateWrapper<CompanyUser>()
                .eq(CompanyUser::getCompanyId, dto.getCompanyId())
                .eq(CompanyUser::getUserId, dto.getUserId())
                .eq(CompanyUser::getStatus, STATE_NORMAL)
                .set(CompanyUser::getStatus, STATE_STOP));
        if (!update) {
            throw new ServiceException("移除企业成员失败");
        }
    }

    @Override
    public CompanyUserVO getUserDetailById(Long userId, Long companyId) {
        CompanyUserVO vo = companyUserMapper.selectByUserIdAndCompanyId(userId, companyId);
        if (!ObjUtil.isNull(vo)) {
            vo.setUserAuthStatusStr(AuthStatusEnum.getInfo(vo.getUserAuthStatus()));
            vo.setUserTypeStr(GcbUserTypeEnum.getInfo(vo.getUserType()));
        }

        //获取邀请当前用户的信息
        GcbUser inviteUser = gcbUserService.getById(vo.getInviteBy());

        //处理用户信息拼接
        String inviteInfo = Optional.ofNullable(inviteUser)
                .map(x -> x.getName() + "(" + PhoneUtil.hideBetween(x.getMobile()) + ")")
                .orElse("");
        vo.setInviteInfo(inviteInfo);
        return vo;
    }
}
